<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="icon" href="/images/logo.jpeg" sizes="192x192">
    <title>大聪明</title>
    <!-- Import style -->
    <link rel="stylesheet" href="//unpkg.com/element-plus/dist/index.css"/>
    <link rel="stylesheet" th:href="@{css/index.css}"/>
    <!-- Import component library -->
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <script src="//unpkg.com/element-plus"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script src="//cdn.jsdelivr.net/npm/@element-plus/icons-vue"></script>
    <script th:src="@{js/eventsource.min.js}"></script>
    <script src="//cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.7.0/build/highlight.min.js"></script>
    <script src="//cdn.jsdelivr.net/npm/highlightjs-line-numbers.js@2.8.0/dist/highlightjs-line-numbers.min.js"></script>
</head>

<body>
<div id="app">
    <el-container class="container">
        <el-header class="title">大聪明</el-header>
        <el-divider></el-divider>
        <el-main ref="main">
            <div style="text-align: center">
                <el-button type="primary" plain @click="getRecord()" :disabled="searching">
                    <el-icon v-if="!searching">
                        <Refresh/>
                    </el-icon>
                    <el-icon v-else class="is-loading">
                        <Loading/>
                    </el-icon>
                    <span style="margin-left: 5px;">加载更多</span>
                </el-button>
            </div>
            <image-com v-for="(el, index) in msgList" :src="el.image" :message="el.msg" :cls="el.cls"
                       :text="el.textCls"/>
            <el-divider>以上是历史记录</el-divider>
        </el-main>
        <el-divider></el-divider>
        <el-footer style="text-align: center;">
            <div class="input_box">
                <el-input v-model="message" placeholder="Please input" clearable class="input" @change="ask"></el-input>
                <el-button class="btn" type="primary" :disabled="loading" @click="ask">
                    <el-icon v-if="!loading">
                        <Promotion/>
                    </el-icon>
                    <el-icon v-else class="is-loading">
                        <Loading/>
                    </el-icon>
                    <span style="margin-left: 5px;">发送</span>
                </el-button>
            </div>
        </el-footer>
    </el-container>
</div>

<script>
    let app = Vue.createApp({
        data() {
            return {
                robot: '/images/logo.png',
                user: '/images/pic03.ico',
                loading: false,
                searching: false,
                msgList: [{image: '/images/logo.png', msg: '请输入问题'}],
                message: undefined,
                pageNum: 0,
                pageSize: 10, // 默认查询10条记录
            }
        },
        watch: {
            loading: {
                handler() {
                    let main = document.querySelector('.el-main');
                    main.scrollTop = main.scrollHeight
                    this.hidden = false
                },
                deep: true,
                flush: 'post'
            },
            pageNum: {
                handler() {
                    let main = document.querySelector('.el-main');
                    main.scrollTop = 0
                },
                deep: true,
                flush: 'post'
            },
        },
        methods: {
            // 开始问答
            ask() {
                if (this.message) {
                    this.msgList.push({
                        image: this.user,
                        msg: this.message,
                        cls: 'img_box_right'
                    })
                    let msg = this.message
                    this.message = ''
                    this.msgList.push({image: this.robot, textCls: 'box', message: '请稍后...'})
                    this.loading = true
                    this.send("/open-ai/chat?question=" + msg)
                } else {
                    alert("请输入问题")
                }
            },
            // 获取历史记录
            getHistory() {
                this.searching = true
                axios({
                    url: '/open-ai/history?pageSize=' + this.pageSize + "&pageNum=" + this.pageNum,
                }).then((res) => {
                    if (res.data.code === 1) { // 查询成功
                        let list = res.data.data
                        list.forEach(e => {
                            this.msgList.unshift({
                                image: this.robot,
                                msg: e.answer
                            })
                            this.msgList.unshift({
                                image: this.user,
                                msg: e.prompt,
                                cls: 'img_box_right'
                            })
                        })
                        this.searching = false
                    }
                })
            },
            getRecord() {
                this.pageNum = this.pageNum + 1
                this.getHistory()
            },
            // 发送请求到后端并处理返回结果
            send(url) {
                let sse;
                const eventSource = new EventSource(url);
                eventSource.onopen = (event) => {
                    sse = event.target;
                };
                eventSource.onmessage = (event) => {
                    if (event.data === "[DONE]") {
                        if (sse) {
                            sse.close()
                        }
                        return;
                    }
                    let json_data = JSON.parse(event.data)
                    if (json_data.role != null) {
                        let el = this.msgList.pop()
                        el.message = json_data.content
                        el.textCls = 'answer current_answer'
                        this.msgList.push(el)
                    } else {
                        if (json_data.content != null && json_data.content !== 'null') {
                            let answer = document.querySelector(".current_answer")
                            if (answer !== null) {
                                answer.innerText += json_data.content
                                let main = document.querySelector('.el-main');
                                main.scrollTop = main.scrollHeight
                            }
                        } else {
                            let answer = document.querySelector(".current_answer")
                            answer.classList.remove("current_answer")
                            this.loading = false
                        }
                    }
                };
                eventSource.onerror = (event) => {
                    alert("服务异常请重试并联系开发者！")
                    if (event.readyState === EventSource.CLOSED) {
                        console.log('connection is closed')
                    } else {
                        console.log("Error occurred", event)
                    }
                    event.target.close()
                };
                eventSource.addEventListener("customEventName", (event) => {
                    console.log("Message id is " + event.lastEventId)
                });
            }
        },
        mounted() {
            let main = document.querySelector('.el-main');
            main.scrollTop = main.scrollHeight
            this.getHistory()
            main.scrollTop = 0
        },
    })
    app.use(ElementPlus)
    app.component('image-com', {
        template: `
          <div class="img_box" :class="cls"><img class="img" :src=src alt=""/>
          <div class="text_box" :class="text" v-text="message"></div>
          </div>
        `,
        props: ['src', 'cls', 'message', 'text'],
    })
    for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
        app.component(key, component)
    }
    app.mount('#app');
</script>
</body>

</html>